package com.cody.date160205;

import com.cody.date160201.RedisClient;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by cody on 16/2/5.
 */
public class Exercise1 {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private Jedis redis = new RedisClient().getJedis();

    public int uniqueCount(String action, String date) {
        String key = action + ":" + date;
        BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
        return users.cardinality();
    }

    public int uniqueCount(String action, String... dates) {
        BitSet all = new BitSet();
        for (String date :
                dates) {
            String key = action + ":" + date;
            BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
            all.or(users);
        }
        return all.cardinality();
    }

    public void setCount(String action, String date, int count) {
        String key = action + ":" + date;
        redis.del(key);
        for (int i = 0; i < count; ++i) {
            redis.setbit(key,i,true);
        }
    }

    public void initCount(String action) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        String endDate = sdf.format(calendar.getTime());
        calendar.add(Calendar.DATE,-6);
        String beginDate = sdf.format(calendar.getTime());
        initCount(action, new DateSpan(beginDate, endDate));
    }

    public void initCount(String action, DateSpan dateSpan) {
        Random rand = new Random(System.currentTimeMillis());
        Calendar start = Calendar.getInstance();
        start.setTime(dateSpan.getBegin());
        int dateCount = dateSpan.getDiff();
        while (dateCount > 0) {
            String date = sdf.format(start.getTime());
            int count = rand.nextInt(2000) + 8000 + rand.nextInt(100);
            setCount(action,date,count);
            --dateCount;
            start.add(Calendar.DATE,1);
        }
    }

    public void testCount() {
        redis.flushAll();
        DateSpan dateSpan;
        String action;
        try {
            action = "use";
            dateSpan = new DateSpan("2016-01-01", "2016-01-31");
            initCount(action, dateSpan);
        } catch (ParseException e) {
            e.printStackTrace();
            return;
        }
        long start = System.currentTimeMillis();
        int sum = 0;
        int diff = dateSpan.getDiff();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateSpan.getBegin());
        while (diff > 0) {
            sum += uniqueCount(action,sdf.format(calendar.getTime()));
            calendar.add(Calendar.DATE, 1);
            --diff;
        }
        System.out.println(sum);
        System.out.println("cost millseconds:" + ((System.currentTimeMillis() - start)));
    }

    public void testPipeline () throws IOException {
        redis.select(0);
        redis.flushDB();
        Pipeline pipeline = redis.pipelined();
        for (int i = 0; i < 10000; i++) {
            pipeline.incr("powerlevel");
        }
        pipeline.sync();
        System.out.println(redis.get("powerlevel"));
    }

    private class DateSpan{
        Date begin;
        Date end;
        int diff;

        public DateSpan() {
        }

        public DateSpan(String begin, String end) throws ParseException {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            this.begin = sdf.parse(begin);
            this.end = sdf.parse(end);
            this.diff = calculateDiff(this.begin, this.end);
        }

        public Date getBegin() {
            return begin;
        }

        public void setBegin(Date begin) {
            this.begin = begin;
        }

        public Date getEnd() {
            return end;
        }

        public void setEnd(Date end) {
            this.end = end;
        }

        public int getDiff() {
            return diff;
        }

        int calculateDiff(Date begin, Date end) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(begin);
            long beginTimeInMs = calendar.getTimeInMillis();
            calendar.setTime(end);
            long endTimeInMs = calendar.getTimeInMillis();
            int diff = (int) ((endTimeInMs - beginTimeInMs) / (1000 * 60 * 60 * 24));
            return (diff + 1);
        }
    }

    static class MainClass{
        public static void main(String[] args) {
            try {
                new Exercise1().testPipeline();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
